/**
 * 全局错误处理
 * 捕获 Vue 错误、Promise 错误、资源加载错误
 */

import type { App } from 'vue'
import logger from './logger'
import { message } from './message'

// 错误类型
export enum ErrorType {
  VUE_ERROR = 'VUE_ERROR',
  PROMISE_ERROR = 'PROMISE_ERROR',
  RESOURCE_ERROR = 'RESOURCE_ERROR',
  NETWORK_ERROR = 'NETWORK_ERROR'
}

// 错误信息接口
interface ErrorInfo {
  type: ErrorType
  message: string
  stack?: string
  componentName?: string
  info?: string
}

// 错误处理器
class ErrorHandler {
  private errorCount = 0
  private maxErrors = 10 // 最大错误数，超过后刷新页面
  private errorTimestamp = Date.now()

  // 处理错误
  private handleError(errorInfo: ErrorInfo): void {
    // 记录日志
    logger.error('捕获到错误', {
      type: errorInfo.type,
      message: errorInfo.message,
      stack: errorInfo.stack,
      componentName: errorInfo.componentName,
      info: errorInfo.info
    })

    // 错误计数（1分钟内）
    const now = Date.now()
    if (now - this.errorTimestamp > 60000) {
      this.errorCount = 0
      this.errorTimestamp = now
    }
    this.errorCount++

    // 错误过多时刷新页面
    if (this.errorCount >= this.maxErrors) {
      message.error('应用出现异常，即将刷新页面')
      setTimeout(() => window.location.reload(), 2000)
      return
    }

    // 显示用户友好的错误提示
    const userMessage = this.getUserMessage(errorInfo)
    message.error(userMessage)
  }

  // 获取用户友好的错误信息
  private getUserMessage(errorInfo: ErrorInfo): string {
    switch (errorInfo.type) {
      case ErrorType.NETWORK_ERROR:
        return '网络请求失败，请检查网络连接'
      case ErrorType.RESOURCE_ERROR:
        return '资源加载失败，请刷新页面重试'
      default:
        return '操作失败，请稍后重试'
    }
  }

  // 安装 Vue 错误处理
  installVueErrorHandler(app: App): void {
    app.config.errorHandler = (err, instance, info) => {
      this.handleError({
        type: ErrorType.VUE_ERROR,
        message: (err as Error).message,
        stack: (err as Error).stack,
        componentName: instance?.$options.name || instance?.$options.__name,
        info
      })
    }
  }

  // 安装全局错误处理
  installGlobalErrorHandler(): void {
    // Promise 错误
    window.addEventListener('unhandledrejection', (event) => {
      event.preventDefault()
      this.handleError({
        type: ErrorType.PROMISE_ERROR,
        message: event.reason?.message || String(event.reason),
        stack: event.reason?.stack
      })
    })

    // 资源加载错误
    window.addEventListener(
      'error',
      (event) => {
        if (event.target !== window) {
          this.handleError({
            type: ErrorType.RESOURCE_ERROR,
            message: `资源加载失败: ${(event.target as HTMLElement)?.getAttribute('src') || (event.target as HTMLElement)?.getAttribute('href')}`
          })
        }
      },
      true
    )
  }
}

export const errorHandler = new ErrorHandler()
